﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Microsoft.Practices.Unity;
using System.Configuration;
using System.Web.Mvc;
using System.Web.Hosting;
using System.Web.Routing;
using Microsoft.Practices.Unity.Configuration;
using GaiNo.Core.Infrastructure;
using GaiNo.Core.Helpers;
using GaiNo.Core.Services;

namespace GaiNo.Core
{
    public class ApplicationContext : HttpApplication, IApplicationContext, IContainerAccessor
    {
        const string _contextKey = "GaiNo.Core.ApplicationContext";
        public static IApplicationContext Current
        {
            get
            {
                IApplicationContext _objApplicationContext = null;
                if (HttpContext.Current != null)
                {
                    if (HttpContext.Current.Session[_contextKey] == null)
                    {
                        if (_objApplicationContext == null)
                        {
                            _objApplicationContext = HttpContext.Current.ApplicationInstance as IApplicationContext;
                        }
                        HttpContext.Current.Session[_contextKey] = _objApplicationContext;
                    }
                    else
                        _objApplicationContext = HttpContext.Current.Session[_contextKey] as IApplicationContext;
                }
                else
                    _objApplicationContext = HttpContext.Current.ApplicationInstance as IApplicationContext;
                return _objApplicationContext;
            }
        }
        /// <summary>
        /// Setup and load application
        /// </summary>
        protected void Application_Start()
        {
            Application["container"] = setupContainer();
            Initialize();
        }
        protected virtual void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }
        protected virtual void Initialize()
        {
            ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));

            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);


        }
        protected virtual void Unload()
        {

        }
        /// <summary>
        /// Clean up and necessary objects in the application
        /// </summary>
        protected void Application_End()
        {
            Unload();
        }
        /// <summary>
        /// Handle any requests made to the application.
        /// </summary>
        /// <param name="sender">Sender of request.</param>
        /// <param name="e">EventArgs for request.</param>
        protected void Application_BeginRequest(object sender, EventArgs e)
        {
        }
        protected virtual void SetupContainer(IUnityContainer container)
        {
            return;
        }
        private IUnityContainer setupContainer()
        {
            IUnityContainer parentContainer = new UnityContainer();
            parentContainer
                .RegisterInstance(new AppSettingsHelper(ConfigurationManager.AppSettings))
                .RegisterInstance(RouteTable.Routes)
                .RegisterInstance(System.Web.Mvc.ModelBinders.Binders)
                .RegisterInstance(ViewEngines.Engines)
                .RegisterInstance(HostingEnvironment.VirtualPathProvider);

            foreach (ConnectionStringSettings connectionString in ConfigurationManager.ConnectionStrings)
                parentContainer.RegisterInstance(connectionString.Name, connectionString.ConnectionString);




            // Create a child container and configure it using any settings in the Unity configuration section of the 
            // web.config file.  This will allow users to override any of the default Oxite object mappings within
            // the config file as Unity will search the child container for dependencies first.
            IUnityContainer container = parentContainer.CreateChildContainer();
            SetupContainer(container);
            UnityConfigurationSection config = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

            if (config!=null && config.Containers.Default != null)
            {
                config.Containers.Default.Configure(container);
            }

            container.RegisterInstance(container);
            return container;

        }

        #region IContainerAccessor 成员

        public IUnityContainer Container
        {
            get { return Application["container"] as IUnityContainer; }
        }

        #endregion

        #region IApplicationContext 成员

        public new IUser User
        {
            get { return Container.Resolve<IUser>(); }
        }

        #endregion

        #region IApplicationContext 成员


        public ILog Log
        {
            get { return Container.Resolve<ILog>(); }
        }

        #endregion

        #region IApplicationContext 成员


        public ICrypto Crypto
        {
            get { return Container.Resolve<ICrypto>(); }
        }

        #endregion

        #region IApplicationContext 成员


        public ILanguageResource LanguageRecource
        {
            get { return Container.Resolve<ILanguageResource>(); }
        }

        public IAuthCode AuthCode
        {
            get { return Container.Resolve<IAuthCode>(); }
        }

        #endregion

        #region IApplicationContext 成员


        public IMessage Message
        {
            get { return Container.Resolve<IMessage>(); }
        }

        #endregion
    }
}
